package com.example.authsystem.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(description = "登录统计数据传输对象")
public class LoginStatsDto {

    @Schema(description = "总登录次数", example = "1500")
    private Long totalLoginCount;

    @Schema(description = "今日登录次数", example = "25")
    private Long todayLoginCount;

    @Schema(description = "今日活跃用户数", example = "18")
    private Long todayActiveUserCount;

    @Schema(description = "昨日登录次数", example = "30")
    private Long yesterdayLoginCount;

    @Schema(description = "昨日活跃用户数", example = "22")
    private Long yesterdayActiveUserCount;

    @Schema(description = "本周登录次数", example = "180")
    private Long weekLoginCount;

    @Schema(description = "本月登录次数", example = "750")
    private Long monthLoginCount;

    @Schema(description = "登录成功率", example = "0.95")
    private Double loginSuccessRate;

    @Schema(description = "平均会话时长（分钟）", example = "45.5")
    private Double avgSessionDuration;

    @Schema(description = "峰值登录时间段", example = "09:00-10:00")
    private String peakLoginHour;

    @Schema(description = "最近7天每日登录统计")
    private List<DailyLoginStat> last7DaysStats;

    @Schema(description = "最近30天每日登录统计")
    private List<DailyLoginStat> last30DaysStats;

    @Schema(description = "每小时登录分布统计")
    private List<HourlyLoginStat> hourlyDistribution;

    @Schema(description = "登录设备类型统计")
    private Map<String, Long> deviceTypeStats;

    @Schema(description = "登录地区统计（前10）")
    private List<LocationLoginStat> topLocations;

    @Schema(description = "登录失败统计")
    private LoginFailureStats failureStats;

    @Schema(description = "统计数据更新时间")
    private LocalDateTime lastUpdatedAt;

    // 内部类：每日登录统计
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "每日登录统计")
    public static class DailyLoginStat {

        @Schema(description = "日期", example = "2024-01-15")
        private LocalDate date;

        @Schema(description = "登录次数", example = "45")
        private Long loginCount;

        @Schema(description = "活跃用户数", example = "32")
        private Long activeUserCount;

        @Schema(description = "新用户登录数", example = "3")
        private Long newUserCount;

        @Schema(description = "登录成功次数", example = "42")
        private Long successCount;

        @Schema(description = "登录失败次数", example = "3")
        private Long failureCount;

        @Schema(description = "平均会话时长（分钟）", example = "38.5")
        private Double avgSessionDuration;
    }

    // 内部类：每小时登录统计
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "每小时登录统计")
    public static class HourlyLoginStat {

        @Schema(description = "小时（0-23）", example = "9")
        private Integer hour;

        @Schema(description = "登录次数", example = "25")
        private Long loginCount;

        @Schema(description = "活跃用户数", example = "20")
        private Long activeUserCount;

        @Schema(description = "时间段描述", example = "09:00-10:00")
        private String timeRange;
    }

    // 内部类：地区登录统计
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "地区登录统计")
    public static class LocationLoginStat {

        @Schema(description = "地区名称", example = "北京市")
        private String location;

        @Schema(description = "登录次数", example = "120")
        private Long loginCount;

        @Schema(description = "活跃用户数", example = "85")
        private Long activeUserCount;

        @Schema(description = "占比", example = "0.08")
        private Double percentage;
    }

    // 内部类：登录失败统计
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Schema(description = "登录失败统计")
    public static class LoginFailureStats {

        @Schema(description = "总失败次数", example = "85")
        private Long totalFailureCount;

        @Schema(description = "今日失败次数", example = "5")
        private Long todayFailureCount;

        @Schema(description = "密码错误次数", example = "60")
        private Long passwordErrorCount;

        @Schema(description = "用户名不存在次数", example = "15")
        private Long usernameNotFoundCount;

        @Schema(description = "账户锁定次数", example = "8")
        private Long accountLockedCount;

        @Schema(description = "其他错误次数", example = "2")
        private Long otherErrorCount;

        @Schema(description = "失败率", example = "0.05")
        private Double failureRate;

        @Schema(description = "最频繁失败的IP地址")
        private List<String> topFailureIps;
    }

    // 便捷方法：创建空的统计对象
    public static LoginStatsDto empty() {
        return LoginStatsDto.builder()
                .totalLoginCount(0L)
                .todayLoginCount(0L)
                .todayActiveUserCount(0L)
                .yesterdayLoginCount(0L)
                .yesterdayActiveUserCount(0L)
                .weekLoginCount(0L)
                .monthLoginCount(0L)
                .loginSuccessRate(0.0)
                .avgSessionDuration(0.0)
                .peakLoginHour("未知")
                .last7DaysStats(List.of())
                .last30DaysStats(List.of())
                .hourlyDistribution(List.of())
                .deviceTypeStats(Map.of())
                .topLocations(List.of())
                .failureStats(LoginFailureStats.builder()
                        .totalFailureCount(0L)
                        .todayFailureCount(0L)
                        .passwordErrorCount(0L)
                        .usernameNotFoundCount(0L)
                        .accountLockedCount(0L)
                        .otherErrorCount(0L)
                        .failureRate(0.0)
                        .topFailureIps(List.of())
                        .build())
                .lastUpdatedAt(LocalDateTime.now())
                .build();
    }

    // 便捷方法：计算环比增长率
    public Double getTodayGrowthRate() {
        if (yesterdayLoginCount == null || yesterdayLoginCount == 0) {
            return 0.0;
        }
        return ((todayLoginCount.doubleValue() - yesterdayLoginCount.doubleValue()) / yesterdayLoginCount.doubleValue()) * 100;
    }

    // 便捷方法：获取活跃用户增长率
    public Double getActiveUserGrowthRate() {
        if (yesterdayActiveUserCount == null || yesterdayActiveUserCount == 0) {
            return 0.0;
        }
        return ((todayActiveUserCount.doubleValue() - yesterdayActiveUserCount.doubleValue()) / yesterdayActiveUserCount.doubleValue()) * 100;
    }

    // 便捷方法：判断是否为高峰期
    public Boolean isPeakTime() {
        LocalDateTime now = LocalDateTime.now();
        int currentHour = now.getHour();

        // 一般认为9-11点和14-16点为高峰期
        return (currentHour >= 9 && currentHour <= 11) || (currentHour >= 14 && currentHour <= 16);
    }

    // 便捷方法：获取登录趋势（上升、下降、平稳）
    public String getLoginTrend() {
        if (last7DaysStats == null || last7DaysStats.size() < 2) {
            return "数据不足";
        }

        // 比较最近3天和前3天的平均值
        if (last7DaysStats.size() >= 6) {
            double recent3DaysAvg = last7DaysStats.stream()
                    .skip(last7DaysStats.size() - 3)
                    .mapToLong(DailyLoginStat::getLoginCount)
                    .average()
                    .orElse(0.0);

            double previous3DaysAvg = last7DaysStats.stream()
                    .skip(last7DaysStats.size() - 6)
                    .limit(3)
                    .mapToLong(DailyLoginStat::getLoginCount)
                    .average()
                    .orElse(0.0);

            double changeRate = (recent3DaysAvg - previous3DaysAvg) / previous3DaysAvg * 100;

            if (changeRate > 5) {
                return "上升";
            } else if (changeRate < -5) {
                return "下降";
            } else {
                return "平稳";
            }
        }

        return "平稳";
    }
}
